#include "clprs.h"
/*
gst-launch -ve udpsrc uri=udp://192.168.52.128:5566 port=5566  caps = "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96" ! rtpjitterbuffer ! rtph264depay ! h264parse ! mp4mux name=mux udpsrc uri=udp://192.168.52.128:5588 port=5588 caps="application/x-rtp" ! rtppcmudepay  ! mulawdec ! audioconvert ! voaacenc  ! mux. mux. ! filesink location=file.mp4
 */
#define VIDEO_CAPS	"application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, payload=(int)96"
#define AUDIO_CAPS	"application/x-rtp"
#define DEST_FILE	"./my.mp4"

clprs_server g_server;

static gboolean clprs_set_src(clprs_server_bin *bin) 
{
	GstCaps *caps;

	g_assert(bin->audpsrc);
	g_assert(bin->vudpsrc);
	if(!bin->uri){
		g_error("No uri presented!");
		return FALSE;
	}
	if(bin->uri->auri_str && bin->uri->aport && bin->uri->acaps){
		g_object_set (G_OBJECT (bin->audpsrc), "uri", bin->uri->auri_str, NULL);
		g_object_set (G_OBJECT (bin->audpsrc), "port", bin->uri->aport, NULL);
		caps = gst_caps_from_string(bin->uri->acaps);
		g_object_set(bin->audpsrc, "caps", caps, NULL);
	}

	if(bin->uri->vuri_str && bin->uri->vport && bin->uri->vcaps){
		g_object_set (G_OBJECT (bin->vudpsrc), "uri", bin->uri->vuri_str, NULL);
		g_object_set (G_OBJECT (bin->vudpsrc), "port", bin->uri->vport, NULL);
		caps = gst_caps_from_string(bin->uri->vcaps);
		g_object_set(bin->vudpsrc, "caps", caps, NULL);
	}

	gst_caps_unref (caps);

	return TRUE;
}

static void clprs_send_eos(GstElement *element)
{
	GstEvent *event;

	event = gst_event_new_eos();
	gst_element_send_event(element, event);
}

static gboolean bus_message(GstBus * bus, GstMessage * message, clprs_server *server)
{
	GST_DEBUG("######## LIDE: Got message %s", gst_message_type_get_name (GST_MESSAGE_TYPE (message)));

	switch (GST_MESSAGE_TYPE (message)) {
		case GST_MESSAGE_ERROR:
			{
				GError *err;
				gchar *debug;

				gst_message_parse_error (message, &err, &debug);
				g_print ("Error: %s\n", err->message);
				g_error_free (err);
				g_free (debug);
				g_main_loop_quit (server->loop);
				break;
			}
		case GST_MESSAGE_EOS:
			{
				/* end-of-stream */
				g_print("\nQuit main loop ......\n");
	//			g_usleep (5 * G_USEC_PER_SEC);
				g_main_loop_quit (server->loop);
				break;
			}
		default:
			break;
	}

	return TRUE;
}

static gboolean clprs_attach_server_bin(GstElement *pipeline, clprs_server_bin *bin)
{
	clprs_server_bin *server_bin = bin;

	
	server_bin->vudpsrc = gst_element_factory_make("udpsrc", "vrtpsrc");

	/* create elements */
	server_bin->vrtpjitterbuffer = gst_element_factory_make("rtpjitterbuffer", "vjitterbuffer");
	server_bin->rtph264depay = gst_element_factory_make("rtph264depay", "h264depay");
	server_bin->h264parse = gst_element_factory_make("h264parse", "h264parse");
 
	server_bin->audpsrc = gst_element_factory_make("udpsrc", "artpsrc");
	if(!clprs_set_src(server_bin)){
		g_error("Set uri err!!");
	}
	server_bin->artpjitterbuffer = gst_element_factory_make("rtpjitterbuffer", "ajitterbuffer");
	server_bin->rtppcmudepay = gst_element_factory_make("rtppcmudepay", "rtppcmudepay");
	server_bin->mulawdec = gst_element_factory_make("mulawdec", "mulawdec");
	server_bin->audioconvert = gst_element_factory_make("audioconvert", "audioconvert");
	server_bin->voaacenc = gst_element_factory_make("voaacenc", "voaacenc");

	gst_bin_add_many(GST_BIN (pipeline), server_bin->vudpsrc, server_bin->vrtpjitterbuffer, server_bin->rtph264depay, server_bin->h264parse, NULL);
	gst_bin_add_many(GST_BIN (pipeline), server_bin->audpsrc,  server_bin->artpjitterbuffer, server_bin->rtppcmudepay, server_bin->mulawdec, server_bin->audioconvert, server_bin->voaacenc, NULL);

}


static clprs_server_bin* clprs_new_server_bin(const gchar *ip, gint aport, gint vport)
{
	clprs_server_bin *bin = (clprs_server_bin*)g_malloc(sizeof(clprs_server_bin));
	
	bin->uri = (clprs_uri_t*)g_malloc(sizeof(clprs_uri_t));
	bin->uri->auri_str = (gchar*)g_malloc(sizeof(char) * 256);
	bin->uri->vuri_str = (gchar*)g_malloc(sizeof(char) * 256);
	sprintf(bin->uri->auri_str, "udp://%s:%d", ip, aport);
	bin->uri->aport = aport;
	bin->uri->acaps= g_strdup(AUDIO_CAPS);
	sprintf(bin->uri->vuri_str, "udp://%s:%d", ip, vport);
	bin->uri->vport = vport;
	bin->uri->vcaps= g_strdup(VIDEO_CAPS);

	return bin;

}

static void clprs_delete_server_bin(clprs_server_bin *bin)
{
	g_free(bin->uri->auri_str);
	g_free(bin->uri->vuri_str);
	g_free(bin->uri->acaps);
	g_free(bin->uri->vcaps);
	g_free(bin->uri);

	g_free(bin);
}

static gboolean clprs_element_link_many(clprs_server_bin *bin, GstElement *mux) 
{
	if(!bin) return FALSE;

	if(!gst_element_link_many(bin->vudpsrc, bin->vrtpjitterbuffer, bin->rtph264depay, bin->h264parse, mux, NULL)){
		g_error("1 Elements link error!");
	}
	if(!gst_element_link_many(bin->audpsrc, bin->artpjitterbuffer, bin->rtppcmudepay, bin->mulawdec, bin->audioconvert, bin->voaacenc, mux, NULL)){
		g_error("2 Elements link error!");
	}
}

int main (int argc, char *argv[]) 
{
	gboolean link_ok;
	GstBus *bus;
	guint bus_watch_id;
	clprs_server *server = &g_server;

	gst_init(&argc, &argv);
	server->loop = g_main_loop_new(NULL, FALSE);//create main loop
	

	/* create a new pipeline */
	server->pipeline = gst_pipeline_new("pipeline");

	server->server_bin[0] = clprs_new_server_bin("192.168.179.118", 5588, 5566);
	clprs_attach_server_bin(server->pipeline, server->server_bin[0]);
	
//	server->server_bin[1] = clprs_new_server_bin("192.168.179.118", 5589, 5567);
//	clprs_attach_server_bin(server->pipeline, server->server_bin[0]);
//	server->is_mix = TRUE;

	server->mp4mux = gst_element_factory_make("mp4mux", "mp4mux");
//	g_object_set(G_OBJECT (server->mp4mux), "fragment-duration", 10, NULL);
	server->filesink = gst_element_factory_make("filesink", "sink");
	g_object_set(G_OBJECT (server->filesink), "location", DEST_FILE, NULL);
	//g_object_set (G_OBJECT (server->filesink), "sync", TRUE, NULL);

	/* add elements to pipeline */
	gst_bin_add_many(GST_BIN (server->pipeline), server->mp4mux, server->filesink, NULL);
	/* link elements */
	if(!gst_element_link(server->mp4mux, server->filesink)){
		g_error("3 Elements link error!");
	}
	clprs_element_link_many(server->server_bin[0], server->mp4mux);

	bus = gst_pipeline_get_bus(GST_PIPELINE(server->pipeline));

	bus_watch_id = gst_bus_add_watch(bus, (GstBusFunc)bus_message, server);
	gst_object_unref (bus);

	g_timeout_add(1000 * 20, (GSourceFunc)clprs_send_eos, server->pipeline);

	/* play */
	gst_element_set_state(server->pipeline, GST_STATE_PLAYING);
	/* main loop */
	g_print("\nStart main loop ......\n");
	g_main_loop_run(server->loop);
	/* stop pipeline */
	gst_element_set_state(server->pipeline, GST_STATE_NULL);
	/* free src */
	gst_object_unref(GST_OBJECT(server->pipeline));
	clprs_delete_server_bin(server->server_bin[0]);
	g_source_remove(bus_watch_id);
	g_main_loop_unref(server->loop);
	exit (0);
}
